package com.dudu.service.impl;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.util.JSONUtils;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.dudu.access.BaiWuSMS;
import com.dudu.access.RedisUtil;
import com.dudu.bean.AccountBean;
import com.dudu.bean.AppExtendBean;
import com.dudu.dao.SmsDao;
import com.dudu.dao.SmsInfoDao;
import com.dudu.model.Signcode;
import com.dudu.model.SmsInfo;
import com.dudu.model.SmsTemplate;
import com.dudu.service.IOperationPlatformService;
import com.dudu.service.ISmsService;
import com.dudu.utils.DateUtils;
import com.dudu.utils.DictionaryUtils;

import core.CoreDao;
import core.CoreDaoInvoke;

public class SmsServiceImpl implements ISmsService {
    private static final Logger log = core.util.Logger.getLogger(SmsServiceImpl.class.getSimpleName());
    // IP白名单
    private SmsDao smsDao = new SmsDao();
    // 短信信息表
    private SmsInfoDao smsInfoDao = new SmsInfoDao();
    // 用于查询数据用
    private CoreDao coreDao = CoreDaoInvoke.getInstance();
    // 运营平台接口
    private IOperationPlatformService operationPlatformService = new OperationPlatformServiceImpl();

    private String smsQueryPeriod = DictionaryUtils.getValueByTypeAndKey("sms", "query_period");	//查询周期
    private String smsErrorPercent = DictionaryUtils.getValueByTypeAndKey("sms", "error_percent");	//短信验证码下发失败率
    /**
     * 发送短信
     * 
     * @param account
     * @param userIdentify
     * @param phones
     * @param template_code
     * @param template_params
     * @param msg_id
     * @param remoteAddr
     * @param up_sms
     *            是否需要上行短信
     * @return
     */
    public JSONObject postSms(AccountBean account, AppExtendBean appExtendBean, String userIdentify, String phones, String template_code, JSONArray template_params, String msg_id,
	    String remoteAddr, String up_sms, String sms_signature) {
	log.info("SmsServiceImpl.postSms");
	JSONObject object = new JSONObject();
	// 校验短信签名
	String sign_code = smsDao.querySigncodeByAppkey(coreDao, appExtendBean.getApp_key());
	if (StringUtils.isBlank(sign_code)) {
	    object.put("result", "-1");
	    object.put("describe", "短信签名错误");
	    object.put("code", "0202");
	    return object;
	}
	// 校验IP白名单
	List<JSONObject> ipJsonArray = smsDao.queryIpBySigncode(coreDao, sign_code);
	if (JSONUtils.isNull(ipJsonArray)) {
	    object.put("result", "-1");
	    object.put("describe", "访问IP错误");
	    object.put("code", "0201");
	    return object;
	} else {
	    if (!checkIp(ipJsonArray, remoteAddr)) {
		object.put("result", "-1");
		object.put("describe", "访问IP错误");
		object.put("code", "0201");
		return object;
	    }
	}
	// 获取签名
	Signcode signcode = smsDao.querySigncodeBycode(coreDao, sign_code);
	String signature = null; // 签名
	String ext_number = null; // 下发号码
	String position = null; // 签名位置
	if (signcode == null) {
	    object.put("result", "-1");
	    object.put("describe", "短信签名错误");
	    object.put("code", "0202");
	    return object;
	} else {
	    signature = signcode.getSignature();
	    ext_number = signcode.getExt_number();
	    position = signcode.getPosition();
	}
	//自定义签名
	if(StringUtils.isNotBlank(sms_signature)){
		if(sms_signature.length() >= 3 && sms_signature.length() <= 8){
			signature = sms_signature;
		}else{
			object.put("result", "-1");
		    object.put("describe", "签名需在3至8个字符以内");
		    object.put("code", "0202");
		    return object;
		}
	}
	// 校验参数
	if (template_params.size() > 10) {
	    object.put("result", "-1");
	    object.put("describe", "短信模板参数错误");
	    object.put("code", "0205");
	    return object;
	}
	for (int j = 0; j < template_params.size(); j++) {
	    String param = template_params.getString(j);
	    if (param.length() > 50) {
		object.put("result", "-1");
		object.put("describe", "短信模板参数错误");
		object.put("code", "0205");
		return object;
	    }
	}
	// 获取模板
	String templateContent = null;
	List<JSONObject> jsonTemplatecodeAndAppkeyList = smsDao.queryByAppkeyAndTemplatecode(coreDao, appExtendBean.getApp_key(), template_code);
	if (jsonTemplatecodeAndAppkeyList.size() == 0) {
	    object.put("result", "-1");
	    object.put("describe", "短信模板错误");
	    object.put("code", "0203");
	    return object;
	} else {
	    SmsTemplate smsTemplate = smsDao.queryTemplateBycode(coreDao, template_code);
	    templateContent = smsTemplate.getTemplate_content();
	}
	// 组装短信正文（）
	StringBuffer smsContentBuffer = new StringBuffer();
	int paramsLength = templateContent.split("\\{").length - 1;
	if (paramsLength != template_params.size()) {
	    object.put("result", "-1");
	    object.put("describe", "短信参数与模板参数不匹配");
	    object.put("code", "0204");
	    return object;
	} else {
	    for (int i = 0; i < paramsLength; i++) {
		templateContent = templateContent.replace("{" + (i + 1) + "}", template_params.get(i).toString()); // 模板参数从1开始
	    }
	}
	if ("before".equals(position)) {
	    smsContentBuffer.append("【" + signature + "】");
	    smsContentBuffer.append(templateContent);
	} else {
	    smsContentBuffer.append(templateContent);
	    smsContentBuffer.append("【" + signature + "】");
	}
	// 发送短信
	String sessionId = UUID.randomUUID().toString();
	String sendResult = null;
	StringBuffer errorNumbers = new StringBuffer();
	if ("1".equalsIgnoreCase(up_sms)) { // 需要上行短信时，每个号码需要一个随机扩展号,
	    String[] phoneArray = phones.split(",");
	    for (String phone : phoneArray) {
		ext_number = getExtNumber(phone);
		String ret = BaiWuSMS.sendSms(phone, smsContentBuffer.toString(), sessionId, ext_number);
		if (StringUtils.isBlank(ret) || !ret.startsWith("0")) {
		    errorNumbers.append(phone + ",");
		}
	    }
	    if (StringUtils.isNotBlank(errorNumbers.toString())) {
		sendResult = "-1";
	    } else {
		sendResult = "0";
	    }
	} else {
	    sendResult = BaiWuSMS.sendSms(phones, smsContentBuffer.toString(), sessionId, ext_number);
	    errorNumbers.append(phones);
	}

	if (StringUtils.isNotBlank(sendResult) && sendResult.startsWith("0")) {
	    object.put("result", "0");
	    object.put("describe", "success");
	    object.put("code", "0000");
	} else {
	    object.put("result", "-1");
	    object.put("describe", "短信发送失败;发送失败号码为:" + errorNumbers);
	    object.put("code", "0200");
	    return object;
	}
	// 存储用户信息--此处有两个用户信息存储方法，暂不做业务修改，在后期需要对此块业务重新编写
	operationPlatformService.manageUserByOP(appExtendBean.getPeriphery_code(), account.getCust_account(), userIdentify.replaceAll(" ", ""));
	// 记录t_sms_info
	this.insertSmsInfo(appExtendBean.getApp_key(), account.getCust_account(), userIdentify, signcode.getSigncode(), signature, template_code, msg_id,
		smsContentBuffer.toString(), phones, sessionId, phones.split(",").length, sendResult.startsWith("0") ? "0" : "-1", sendResult, remoteAddr, "", ext_number);

	return object;
    }

    /**
     * 增加SMSINFO
     * 
     * @param app_key
     * @param cust_account
     * @param user_identifer
     * @param signcode
     * @param signature
     * @param template_code
     * @param msg_id
     * @param content
     * @param phones
     * @param session_id
     * @param phones_amount
     * @param status
     * @param status_desc
     * @param ip
     * @param comments
     * @return
     */
    private int insertSmsInfo(String app_key, String cust_account, String user_identifer, String signcode, String signature, String template_code, String msg_id, String content,
	    String phones, String session_id, int phones_amount, String status, String status_desc, String ip, String comments, String ext_number) {
	int result = -1;
	try {
	    SmsInfo bean = new SmsInfo();
	    bean.setApp_key(app_key);
	    // bean.setAccount_id(account_id);
	    bean.setCust_account(cust_account);
	    bean.setUser_identifer(user_identifer);
	    bean.setSigncode(signcode);
	    bean.setSignature(signature);
	    bean.setTemplate_code(template_code);
	    bean.setMsg_id(msg_id);
	    bean.setContent(content);
	    bean.setPhones(phones);
	    bean.setSession_id(session_id);
	    bean.setPhones_amount(phones_amount);
	    bean.setStatus(status);
	    bean.setStatus_desc(status_desc);
	    bean.setAudit_status("");
	    bean.setAudit_desc("");
	    bean.setAudit_time(null);
	    bean.setIp(ip);
	    bean.setComments(comments);
	    bean.setExt_number(ext_number);
	    result = this.smsInfoDao.insert(coreDao, bean);
	} catch (Exception ex) {
	    ex.printStackTrace();
	}

	return result;
    }

    /**
     * 校验IP白名单
     * 
     * @param ipJsonArray
     * @param remoteAddr
     * @return
     */
    private boolean checkIp(List<JSONObject> ipJsonArray, String remoteAddr) {
	boolean result = false;
	if (StringUtils.isNotBlank(remoteAddr)) {
	    for (JSONObject ipJson : ipJsonArray) {
		String ip = ipJson.getString("ip");
		if (remoteAddr.equalsIgnoreCase(ip)) {
		    result = true;
		    continue;
		}
	    }
	}
	return result;
    }

    /**
     * 获取扩展号 同一个手机号的下发扩展号不能和上次的下发扩展号一样， 扩展号取值返回4000 -
     * 4999，第一次是使用4000，逐次递增，到4999时重新从4000开始
     * 
     * @return
     */
    private String getExtNumber(String phone) {
	if (StringUtils.isBlank(phone)) {
	    return "";
	}
	String redisKey = "sms:ext:phone:" + phone; // redis主键dudu:open:sms:ext:phone:17001090122
	String extNumber = ""; // 4000至4999
	String lastExtNumber = RedisUtil.getString(redisKey); // 上次使用的下发扩展号，第一次下发时返回值为空
	if (StringUtils.isBlank(lastExtNumber)) {
	    extNumber = "4000";
	    RedisUtil.setString(redisKey, extNumber); // 第一次时使用【4000】这个下发扩展号存入redis
	} else {
	    extNumber = String.valueOf((Integer.valueOf(lastExtNumber) + 1));
	    if (Integer.valueOf(extNumber) == 5000) {
		extNumber = "4000";
	    }
	    if (extNumber.equals(lastExtNumber)) {
		extNumber = getExtNumber(redisKey); // 和上次使用的扩展号相同，重新获取
	    } else {
		RedisUtil.setString(redisKey, extNumber); // 把本次使用的下发扩展号存入redis
	    }
	}

	return String.valueOf(extNumber);
    }


	@Override
	public int queryErrorAmounts() {
		int errorAmount = 0;
		int period = 10; 
		if(StringUtils.isNotBlank(smsQueryPeriod)){
			period = Integer.valueOf(smsQueryPeriod);
		}
		Date now = new Date();
		Date now_10 = new Date(now.getTime() - period*60*1000); 
		String beginTime = DateUtils.getFormatTime(now_10, "yyyy-MM-dd HH:mm:ss");  
		String endTime = DateUtils.getFormatTime(now, "yyyy-MM-dd HH:mm:ss");	
		JSONObject dataJson = smsInfoDao.queryErrorAmounts(coreDao, beginTime, endTime);
		if(dataJson != null){
			errorAmount = dataJson.optInt("errorAmount");
		}	
		return errorAmount;
	}

	@Override
	public int queryDelayAmounts() {
		int delayAmount = 0;
		int noStatusAmount = 0;
		int period = 10; 
		if(StringUtils.isNotBlank(smsQueryPeriod)){
			period = Integer.valueOf(smsQueryPeriod);
		}
		Date now = new Date();
		Date now_10 = new Date(now.getTime() - period*60*1000); 
		String beginTime = DateUtils.getFormatTime(now_10, "yyyy-MM-dd HH:mm:ss");  
		String endTime = DateUtils.getFormatTime(now, "yyyy-MM-dd HH:mm:ss");	
		JSONObject dataJson = smsInfoDao.queryDelayAmounts(coreDao, beginTime, endTime);
		if(dataJson != null){
			delayAmount = dataJson.optInt("delayAmount");
			noStatusAmount = dataJson.optInt("noStatusAmount");
		}	
		return delayAmount+noStatusAmount;
	}
	
	@Override
	public double queryErrorPercent() {
		double result = 0;
		int period = 60; 
		if(StringUtils.isNotBlank(smsQueryPeriod)){
			period = Integer.valueOf(smsQueryPeriod);
		}
		Date now = new Date();
		Date now_60 = new Date(now.getTime() - period*60*1000); 
		String beginTime = DateUtils.getFormatTime(now_60, "yyyy-MM-dd HH:mm:ss");  
		String endTime = DateUtils.getFormatTime(now, "yyyy-MM-dd HH:mm:ss");	
		JSONObject dataJson = smsInfoDao.queryErrorPercent(coreDao, beginTime, endTime);
		if(dataJson != null){
			double percent = dataJson.optDouble("per");
			double errorPercent = 0.05; //默认失败率
			if(StringUtils.isNotBlank(smsErrorPercent)){
				errorPercent = Double.valueOf(smsErrorPercent);
			}
			
			if(percent >= errorPercent){
				result = percent;
			}
		}	
		return result;
	}
	
    public static void main(String[] args) {
	for (int i = 0; i < 10; i++) {
	    SmsServiceImpl SmsServiceImpl = new SmsServiceImpl();
	    System.out.println(SmsServiceImpl.getExtNumber("57001090126"));
	}
    }

}
